package HereClass;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;

/**
 * Classe bando de dados, adiciona, pesquisa e remove os Usuario
 * 
 * @author Caio, Ronaldo, Enio e Rafael
 * @version 5.1
 */
public class BancoDeDados {

	private static BancoDeDados instanciaUnicaBD;

	protected BancoDeDados() {
	}

	private final String USUARIO = "usuarios_dados";
	private final String CONVITE = "convites_pendentes";

	public static BancoDeDados getInstance() {
		if (instanciaUnicaBD == null)
			instanciaUnicaBD = new BancoDeDados();
		return instanciaUnicaBD;
	}

	private ArrayList retornaXMLEmArray(String tipo) {
		if (tipo.equals(USUARIO)) {
			return retornaArrayUsuario();
		} else if (tipo.equals(CONVITE)) {
			return retornaArrayConvite();
		}
		return null;
	}

	private ArrayList<Usuario> retornaArrayUsuario() {
		try {
			BufferedReader in = new BufferedReader(new FileReader(USUARIO
					+ ".txt"));
			String line;
			ArrayList<Usuario> usuarios = new ArrayList<Usuario>();
			while ((line = in.readLine()) != null) {
				usuarios.add(textoToUsuario(line));
			}
			in.close();
			return usuarios;
		} catch (Exception e) {
			return null;
		}
	}

	private ArrayList<Convite> retornaArrayConvite() {
		try {
			BufferedReader in = new BufferedReader(new FileReader(CONVITE
					+ ".txt"));
			String line;
			ArrayList<Convite> convites = new ArrayList<Convite>();
			while ((line = in.readLine()) != null) {
				convites.add(textoToConvite(line));
			}
			in.close();
			return convites;
		} catch (Exception e) {
			return null;
		}

	}

	private boolean gravaArrayEmXML(ArrayList array, String tipo) {
		if (tipo.equals(USUARIO)) {
			return gravaUsuarios(array);
		} else if (tipo.equals(CONVITE)) {
			return gravaConvites(array);
		}
		return false;
	}

	private boolean gravaConvites(ArrayList<Convite> array) {
		ObjectOutputStream out;
		try {
			out = new ObjectOutputStream(new FileOutputStream(CONVITE + ".txt"));
			for (int i = 0; i < array.size(); i++) {
				out.writeUTF(conviteToTexto(array.get(i)));
			}
			out.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private boolean gravaUsuarios(ArrayList<Usuario> array) {
		ObjectOutputStream out;
		try {
			out = new ObjectOutputStream(new FileOutputStream(USUARIO + ".txt"));
			for (int i = 0; i < array.size(); i++) {
				out.writeUTF(usuarioToTexto(array.get(i)));
			}
			out.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private Usuario textoToUsuario(String text) {
		Usuario user = new Usuario();
		String[] array = text.split("|");
		if(!array[0].equalsIgnoreCase("null"))
			user.setUserName(array[0]);
		
		if(!array[1].equalsIgnoreCase("null"))
			user.setSenha(array[1]);
		
		if(!array[2].equalsIgnoreCase("null"))
			user.setNome(array[2]);
		
		if(!array[3].equalsIgnoreCase("null"))
			user.setEmail(array[3]);
		
		if(!array[4].equalsIgnoreCase("null"))
			user.setTelefone(array[4]);
		
		if(!array[5].equalsIgnoreCase("null"))
			user.setLatitude(array[5]);
		
		if(!array[6].equalsIgnoreCase("null"))
			user.setLongitude(array[6]);
		
		String[] contatos = array[7].split(";");
		for (String contato : contatos) {
			String[] atributos = contato.split(",");
			Contato contatoN = new Contato();
			
			if(!atributos[0].equalsIgnoreCase("null"))
				contatoN.setUserName(atributos[0]);
			
			if(!atributos[1].equalsIgnoreCase("null"))
				contatoN.setNome(atributos[1]);
			
			contatoN.setModo(Integer.valueOf(atributos[2]));
			user.addContato(contatoN);
		}
		return user;
	}

	private String usuarioToTexto(Usuario usuario) {
		String user = "";
		user += usuario.getUserName() + "|";
		user += usuario.getSenha() + "|";
		user += usuario.getNome() + "|";
		user += usuario.getEmail() + "|";
		user += usuario.getTelefone() + "|";
		user += usuario.getLatitude() + "|";
		user += usuario.getLongitude() + "|";
		ArrayList<Contato> contatos = usuario.getContatos();
		for (int i = 0; i < contatos.size(); i++) {
			user += contatos.get(i).getUserName() + ",";
			user += contatos.get(i).getNome() + ",";
			user += contatos.get(i).getModo() + ";";
		}
		return user;
	}

	private Convite textoToConvite(String texto) {
		String[] array = texto.split("|");
		Convite convite = new Convite();
		if(!array[0].equalsIgnoreCase("null"))
			convite.setFrom(array[0]);
		
		if(!array[1].equalsIgnoreCase("null"))
			convite.setTo(array[1]);
		
		return convite;
	}

	private String conviteToTexto(Convite convite) {
		return convite.getFrom() + "|" + convite.getTo();

	}

	/**
	 * Cria um usuário no arquivo
	 * 
	 * @param salva
	 * @param tipo
	 * @return boolean
	 */
	public boolean create(Salvavel salva, String tipo) {

		// -------------------------------------------------------------
		// Grava usuario na xml
		// -------------------------------------------------------------

		ArrayList<Salvavel> objSalvavel = retornaXMLEmArray(tipo);
		if (objSalvavel == null) {
			objSalvavel = new ArrayList<Salvavel>();
		}
		objSalvavel.add(salva);
		Collections.sort(objSalvavel);
		return gravaArrayEmXML(objSalvavel, tipo);
		// -------------------------------------------------------

	}

	/**
	 * Atualiza Usuario
	 * 
	 * @param salva
	 * @param tipo
	 */
	public void update(Salvavel salva, String tipo) {

		ArrayList<Salvavel> objSalvaveis = retornaXMLEmArray(tipo);

		for (int i = 0; i < objSalvaveis.size(); i++) {
			if (objSalvaveis.get(i).equals(salva)) {
				objSalvaveis.remove(i);
				objSalvaveis.add(i, salva);
				break;
			}
		}
		gravaArrayEmXML(objSalvaveis, tipo);
	}

	/**
	 * Deleta Usuario
	 * 
	 * @param salva
	 * @param tipo
	 */
	public boolean delete(Salvavel salva, String tipo) {

		ArrayList<Salvavel> objSalvaveis = retornaXMLEmArray(tipo);

		// Remove usuario

		for (int i = 0; i < objSalvaveis.size(); i++) {
			if (objSalvaveis.get(i).equals(salva)) {
				objSalvaveis.remove(i);
				break;
			}
		}
		return gravaArrayEmXML(objSalvaveis, tipo);
	}

	/**
	 * Retorna Usuario pelo UserName
	 * 
	 * @param atributo
	 * @param tipo
	 * @param indice
	 * @return Usuario - null(caso contrario)
	 */
	public Salvavel retrieve(String atributo, String tipo, int indice) {

		ArrayList<Salvavel> usuarios = retornaXMLEmArray(tipo);

		if (usuarios != null) {
			for (int i = 0; i < usuarios.size(); i++) {
				if (usuarios.get(i).meuAtributo(atributo))
					return usuarios.get(i + indice - 1);
			}
		}
		return null;
	}

	/**
	 * Apaga todos os arquivos de Banco de Dados
	 */
	public void deletarArquivo(String tipo) {
		new File(tipo).delete();
	}

}